"---------------------------------------------
" vundle 加载
"---------------------------------------------

let $BUNDLE = expand("$HOME/.vim/bundle")
let $PLUG_DIR = expand("$HOME/.vim/autoload")
if empty(glob(expand("$PLUG_DIR/plug.vim")))
    silent !curl -fLo $PLUG_DIR/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
    autocmd VimEnter * PlugInstall --sync | source ~/.vimrc
endif

if !exists('g:ProjectMark')
    let g:ProjectMark = ['.']
endif

" 定义快捷键的前缀，即<leader> 
let mapleader=";"

call plug#begin(expand($BUNDLE))
"---------------------------------------------
" tags 符号定义插件
"---------------------------------------------
if index(g:bundle_group, "tags") >= 0
    " 显示符号定义插件
    Plug 'majutsushi/tagbar'
    " 自动生成tags
    Plug 'ludovicchabant/vim-gutentags'
    " gtags辅助工具
    Plug 'skywind3000/gutentags_plus'
    Plug 'skywind3000/vim-preview'
    " airline 增加状态栏
    Plug 'vim-airline/vim-airline'
    Plug 'vim-airline/vim-airline-themes'

    nnoremap <F10> :TagbarToggle<CR> 
    inoremap <F10> <ESC>:TagbarToggle<CR>
    let g:tagbar_ctags_bin = 'ctags'
    let g:tagbar_width = 40
    " tagbar一打开，光标即在tagbar页面内
    let g:tagbar_autofocus = 1

    " gutentags搜索工程目录的标志，当前文件路径向上递归直到碰到这些文件/目录名
    let g:gutentags_project_root = copy(g:ProjectMark)
    " 取消添加默认工程目录的标志
    let g:gutentags_add_default_project_roots = 0

    " 对软链接目录生成tag
    let g:gutentags_resolve_symlinks = 1

    " 所生成的数据文件的名称
    let g:gutentags_ctags_tagfile = '.tags'
    " 同时开启ctags和gtags支持
    let g:gutentags_modules = []
    if executable('ctags')
        let g:gutentags_modules += ['ctags']
    endif
    if executable('gtags-cscope') && executable('gtags')
        let g:gutentags_modules += ['gtags_cscope']
    endif
    " 将自动生成的ctags/gtags文件全部放入~/.cache/tags目录中
    let g:gutentags_cache_dir = expand('~/.cache/tags')
    " 配置ctags的参数
    let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
    let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
    let g:gutentags_ctags_extra_args += ['--c-kinds=+px']
    " 如果使用universal ctags需要增加下面一行
    "let g:gutentags_ctags_extra_args += ['--output-format=e-ctags']
    " 禁用gutentags自动加载gtags数据库行为
    let g:gutentags_auto_add_gtags_cscope = 0
    " 调试用
    "let g:gutentags_define_advanced_commands = 1

    " s 查找符号
    " g 查找定义
    " d 查找被这个函数调用的函数
    " c 查找调用这个函数的函数
    " t 查找这个字符串
    " e 查找这个egrep匹配模式
    " f 查找这个文件
    " i 查找include这个文件的文件
    " a 查找这个符号赋值的地方

    " 禁用gutentags_plus自带的快捷键
    let g:gutentags_plus_nomap = 1

    nnoremap <F12> :GscopeFind g <C-R><C-W><cr>
    inoremap <F12> :GscopeFind g <C-R><C-W><cr>

    nnoremap <silent> <leader>gs :GscopeFind s <C-R><C-W><cr>
    nnoremap <silent> <leader>gg :GscopeFind g <C-R><C-W><cr>
    inoremap <silent> <leader>gs :GscopeFind s <C-R><C-W><cr>
    inoremap <silent> <leader>gg :GscopeFind g <C-R><C-W><cr>

    nnoremap <silent> <leader>gc :GscopeFind c <C-R><C-W><cr>
    nnoremap <silent> <leader>gt :GscopeFind t <C-R><C-W><cr>
    nnoremap <silent> <leader>ge :GscopeFind e <C-R><C-W><cr>
    nnoremap <silent> <leader>gf :GscopeFind f <C-R>=expand("<cfile>")<cr><cr>
    nnoremap <silent> <leader>gi :GscopeFind i <C-R>=expand("<cfile>")<cr><cr>
    nnoremap <silent> <leader>gd :GscopeFind d <C-R><C-W><cr>
    nnoremap <silent> <leader>ga :GscopeFind a <C-R><C-W><cr>

    "nnoremap <F2> :PreviewScroll -1<cr>
    "nnoremap <F3> :PreviewScroll +1<cr>
    "inoremap <F2> <c-\><c-o>:PreviewScroll -1<cr>
    "inoremap <F3> <c-\><c-o>:PreviewScroll +1<cr>

    autocmd FileType qf nnoremap <silent><buffer> p :PreviewQuickfix<cr>
    autocmd FileType qf nnoremap <silent><buffer> P :PreviewClose<cr>

    "let g:airline_powerline_fonts = 1
    if !exists('g:airline_symbols')
        let g:airline_symbols = {}
    endif
    let g:airline_left_sep = ''
    let g:airline_left_alt_sep = ''
    let g:airline_right_sep = ''
    let g:airline_right_alt_sep = ''
    let g:airline#extensions#whitespace#enabled = 0
    let g:airline#extensions#tagbar#enabled = 1
    " 如果卡顿可以换成nearest-stl或者nearest
    let g:airline#extensions#tagbar#searchmethod = 'scoped-stl'
"    let g:airline#extensions#tagbar#searchmethod = 'nearest-stl'
"    let g:airline#extensions#tagbar#searchmethod = 'nearest'

    let g:airline#extensions#tabline#enabled=1 "顶部tab显示"
    let g:airline#extensions#tabline#show_splits = 1
    let g:airline#extensions#tabline#show_tabs = 1
    let g:airline#extensions#tabline#show_tab_nr = 1
    let g:airline#extensions#tabline#formatter = 'default'
    let g:airline#extensions#tabline#tab_min_count = 1
    let g:airline#extensions#tabline#tab_nr_type = 2    "splits and tab number
    let g:airline#extensions#tabline#show_buffers = 1
    let g:airline#extensions#tabline#buffer_nr_show = 1
    let g:airline#extensions#tabline#buffer_nr_format = '%s: '
    let g:airline#extensions#tabline#buffer_min_count = 1
    let g:airline#extensions#tabline#show_close_button = 0
    let g:airline#extensions#tabline#left_sep = ''
    let g:airline#extensions#tabline#left_alt_sep = ''
    let g:airline#extensions#tabline#right_sep = ''
    let g:airline#extensions#tabline#right_alt_sep = ''

    nnoremap <leader>n :bn<CR>
    nnoremap <leader>p :bp<CR>

    " 总是显示状态栏 
    set laststatus=2
    let g:airline_theme="bubblegum"
endif

"---------------------------------------------
" nerdtree 浏览文件结构插件
"---------------------------------------------
if index(g:bundle_group, "nerdtree") >= 0
    Plug 'scrooloose/nerdtree'

    " 启动vim时自动打开NERDTree 
    "autocmd VimEnter * NERDTree
    " 设置NERDTree子窗口宽度
    let NERDTreeWinSize=30
    " 设置NERDTree子窗口位置
    let NERDTreeWinPos="left"
    " 显示隐藏文件
    let NERDTreeShowHidden=1
    " NERDTree 子窗口中不显示冗余帮助信息
    let NERDTreeMinimalUI=1
    " 删除文件时自动删除文件对应 buffer
    let NERDTreeAutoDeleteBuffer=1  
    "没有文件时自动打开NERDTree
    autocmd StdinReadPre * let s:std_in=1
    autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif                             
    " 只剩 NERDTree时自动关
    autocmd BufEnter * nested if 0 == len(filter(range(1, winnr('$')), 'empty(getbufvar(winbufnr(v:val), "&bt"))')) | qa! | endif
    nnoremap <F9> :NERDTreeToggle<CR>
endif

"---------------------------------------------
" buffer buffer插件(不需要了)
"---------------------------------------------
if index(g:bundle_group, "buffer") >= 0
    Plug 'ap/vim-buftabline'

    "set hidden
    nnoremap <leader>n :bnext<CR>
    nnoremap <leader>p :bprev<CR>
    highlight BufTabLineCurrent cterm=bold gui=bold ctermfg=236 ctermbg=150
    highlight BufTabLineActive cterm=bold gui=bold ctermfg=151 ctermbg=238
    highlight BufTabLineHidden cterm=bold gui=bold ctermfg=151 ctermbg=234
    highlight BufTabLineFill ctermbg=234
    let g:buftabline_numbers = 1
    let g:buftabline_show = 2
    let g:buftabline_separators = 'on'
endif

"---------------------------------------------
" diff插件
"---------------------------------------------
if index(g:bundle_group, "diff") >= 0
    Plug 'mhinz/vim-signify'

    let g:signify_realtime = 1
    nnoremap <leader>diff :SignifyDiff!<CR>

    highlight DiffAdd cterm=bold gui=bold ctermfg=119 ctermbg=235
    highlight DiffDelete cterm=bold gui=bold ctermfg=167 ctermbg=235
    highlight DiffChange cterm=bold gui=bold ctermfg=227 ctermbg=235
endif

"---------------------------------------------
" LeaderF 文件查找
"---------------------------------------------
if index(g:bundle_group, "LeaderF") >= 0
    Plug 'Yggdroot/LeaderF', { 'do': './install.sh' }

    " 查找文件
    let g:Lf_ShortcutF = '<c-p>'
    " 查找Buffer <leader>b
    let g:Lf_ShortcutB = '<c-b>'
    " 过去常用文件
    nnoremap <c-n> :LeaderfMru<cr>
    " 打开函数搜索
    nnoremap <leader>f :LeaderFunction!<cr>
    " 打开Buffer搜索
    nnoremap <leader>b :LeaderfBuffer<cr>
    " 打开标签搜索
    "noremap <m-m> :LeaderfTag<cr>
    let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }

    let g:Lf_RootMarkers = copy(g:ProjectMark)
    let g:Lf_UseVersionControlTool = 0
    let g:Lf_WorkingDirectoryMode = 'Ac'
    let g:Lf_WindowHeight = 0.30
    let g:Lf_CacheDirectory = expand('~/.cache/leaderf-cache')
    let g:Lf_ShowRelativePath = 0
    let g:Lf_HideHelp = 1
    let g:Lf_StlColorscheme = 'bubblegum'
    let g:Lf_PreviewResult = {'Function':1, 'BufTag':1, 'Buffer':1}
    let g:Lf_ShowDevIcons = 0   " 修复图标乱码

    " 处理软链接相关
    let g:Lf_GtagsSkipSymlink = 'f'
    let g:Lf_FollowLinks = 1

    let g:Lf_WildIgnore = {
        \ 'dir': ['.svn', '.git'],
        \ 'file': ['*.o', '*.so']
        \}
endif

"---------------------------------------------
" ctrlp 文件查找
"---------------------------------------------
if index(g:bundle_group, "ctrlp") >= 0
    Plug 'ctrlpvim/ctrlp.vim'

    let g:ctrlp_map = '<c-p>'
    "let g:ctrlp_cmd = 'CtrlPMixed'
    let g:ctrlp_cmd = 'CtrlP'
    let g:ctrlp_working_path_mode = 'ca'
    let g:ctrlp_by_filename = 1
    let g:ctrlp_switch_buffer = 'Et'

    " 处理软链接相关
    let g:ctrlp_follow_symlinks = 1
    set wildignore+=*/tmp/*,*.so,*.sw*,*.o,*.zip,*.a,*.zip,*.gz
endif

"---------------------------------------------
" YouCompleteMe 
"---------------------------------------------
if index(g:bundle_group, "YCM") >= 0
    Plug 'Valloric/YouCompleteMe', {'for': ['c', 'cpp', 'h', 'hpp', 'cc', 'go']}

    set completeopt=menu,longest 
    if (!exists('g:ycm_extra_conf'))
        let g:ycm_extra_conf = '~/.vim/.ycm_extra_conf.py'    " 配置全局路径
    endif
    let g:ycm_global_ycm_extra_conf = g:ycm_extra_conf    " 配置全局路径
    let g:ycm_confirm_extra_conf = 0    " 每次直接加载该文件，不提示是否要加载
    let g:ycm_min_num_of_chars_for_completion=2 " 从第1个键入字符就开始罗列匹配项
    let g:ycm_seed_identifiers_with_syntax = 1  " 语法关键字补全
    let g:ycm_key_list_select_completion = ['<Down>']  " 映射按键, 没有这个会拦截掉tab, 导致其他插件的tab不能用.
    let g:ycm_key_list_previous_completion = ['<Up>']
    let g:ycm_show_diagnostics_ui = 0    "禁用语法检查
    " 让YouCompleteMe同时利用原来的ctags 
    let g:ycm_collect_identifiers_from_tag_files = 1
    " 每次重新生成匹配项，禁止缓存匹配项
    let g:ycm_cache_omnifunc=0
    " 不查询ultisnips提供的代码模板补全，如果需要，设置成1即可
    let g:ycm_use_ultisnips_completer=0
    " 语义补全
    let g:ycm_semantic_triggers =  {
                \ 'c,cpp,cc,python,java,go,erlang,perl': ['re!\w{2}'],
                \ 'cs,lua,javascript': ['re!\w{2}'],
            \ }
    " 白名单
    let g:ycm_filetype_whitelist = { 
                \ "c":1,
                \ "cpp":1, 
                \ "cc":1,
                \ "h":1,
                \ "hpp":1,
                \ "python":1,
                \ "java":1,
                \ "go":1,
                \ "erlang":1,
                \ "lua":1,
                \}
    " 跳到定义片
    "map <F12> :YcmCompleter GoToDefinitionElseDeclaration<CR>
    "imap <F12> <ESC> :YcmCompleter GoToDefinitionElseDeclaration <CR>
    "map gd :YcmCompleter GoToDefinition <CR>
    "map gl :YcmCompleter GoToDeclaration <CR>
endif

"---------------------------------------------
" cpp-highlight 
"---------------------------------------------
if index(g:bundle_group, "cpp-highlight") >= 0
    Plug 'octol/vim-cpp-enhanced-highlight', {'for': ['c', 'cpp', 'h', 'hpp', 'cc']}

    let g:cpp_class_scope_highlight = 1
    let g:cpp_member_variable_highlight = 1
    let g:cpp_class_decl_highlight = 1
    " 会导致卡顿
"    let g:cpp_experimental_simple_template_highlight = 1   
    let g:cpp_experimental_template_highlight = 1
    let g:cpp_concepts_highlight = 1
    let g:cpp_no_function_highlight = 1
endif

"---------------------------------------------
" echodoc 
"---------------------------------------------
if index(g:bundle_group, "echodoc") >= 0
    Plug 'Shougo/echodoc.vim', {'for': ['c', 'cpp', 'h', 'hpp', 'cc']}

    set noshowmode
    let g:echodoc#enable_at_startup = 1
endif

"---------------------------------------------
" ale 
"---------------------------------------------
if index(g:bundle_group, "ale") >= 0
    Plug 'dense-analysis/ale'

    if !exists('g:ale_include_path')
        let g:ale_include_path = ''
    endif
    let g:ale_linters_explicit = 1
    let g:ale_linters = {'cpp': ['clang', 'gcc'], 'cc': ['clang', 'gcc'], 'go': ['gometalinter', 'gofmt']}
    let g:ale_c_parse_makefile = 1
    let g:ale_completion_delay = 500
    let g:ale_echo_delay = 20
    let g:ale_lint_delay = 500
    let g:ale_echo_msg_format = '[%linter%] %code: %%s'
    let g:ale_lint_on_text_changed = 'normal'
    let g:ale_lint_on_insert_leave = 1
    let g:airline#extensions#ale#enabled = 1

    let g:ale_cpp_cc_executeable = "gcc"
    let g:ale_cpp_cc_options = '-Wall -Wno-mismatched-tags -Wno-expansion-to-defined -O0 -std=c++14 ' . g:ale_include_path
    let g:ale_cpp_clangcheck_options = '-Wall -Wno-mismatched-tags -Wno-expansion-to-defined -O0 -std=c++14 ' . g:ale_include_path
    let g:ale_set_loclist = 0
    let g:ale_set_quickfix = 1
    let g:ale_open_list = 1
    "let g:ale_keep_list_window_open = 1
    let g:ale_set_highlights = 0
    let g:ale_sign_error = "◉"
    let g:ale_sign_warning = "◉"
    highlight ALEErrorSign cterm=bold gui=bold ctermfg=196 ctermbg=235
    highlight ALEWarningSign cterm=bold gui=bold ctermfg=208 ctermbg=235
    highlight ALEWarningLine ctermfg=208 cterm=underline
    highlight ALEErrorLine ctermfg=196 cterm=underline
endif

"---------------------------------------------
" a.vim 头文件和cpp文件跳转 
"---------------------------------------------
if index(g:bundle_group, "a") >= 0
    Plug 'micbou/a.vim', {'for': ['c', 'cpp', 'h', 'hpp', 'cc']}

    nnoremap <F11> :AV<CR>
    inoremap <F11> <ESC>:AV<CR>
endif

"---------------------------------------------
" quickfix
"---------------------------------------------
if index(g:bundle_group, "qf") >= 0
    Plug 'romainl/vim-qf'

    " 设置quick fix最大高度为
    let g:qf_max_height = 8
    nnoremap <silent> C :cclose<cr>

endif

"---------------------------------------------
" snippets 
"---------------------------------------------
if index(g:bundle_group, "snippets") >= 0
    Plug 'honza/vim-snippets'
    Plug 'SirVer/ultisnips'

    let g:UltiSnipsExpandTrigger="<tab>"
    let g:UltiSnipsListSnippets="<s-tab>"
    let g:UltiSnipsJumpForwardTrigger="<tab>"
    let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
    let g:UltiSnipsSnippetDirectories=["UltiSnips", "mysnippets"]
endif

"---------------------------------------------
" vim-go
"---------------------------------------------
if index(g:bundle_group, "go") >= 0
    Plug 'fatih/vim-go'
    " 安装完之后执行:GoInstallBinaries
endif

"---------------------------------------------
" rust-lang/rust.vim
"---------------------------------------------
if index(g:bundle_group, "rust") >= 0
    Plug 'rust-lang/rust.vim'
endif

call plug#end()
